<!-- 聊天 -- 入口 -->
<template>
  <div class="chat_container">
    <!-- <el-input v-model="sendText" placeholder="请输入内容"></el-input> -->
    <!-- <el-button type="primary" @click="sendMsg">发送</el-button> -->
    <div id="my_container"></div>
    <div id="you_container"></div>

    <div class="ui_container">
      <div class="overBackground">
        <div class="user_info">
          <div>
            <span></span>
            <span>张飞</span>
          </div>
        </div>

        <div class="btn_img">
          <div></div>
          <img src="../assets/1.png" @click="acceptCall" alt="">
          <div></div>
          <img src="../assets/2.png" alt="">
          <div></div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      nim: "",
      toUser: {
        // 发给谁
        account: "aa",
        token: "123456",
        logo: "",
        name: ""
      },
      myUser: {
        // 自己的
        account: "bb",
        token: "123456",
        logo: ""
      },
      sendText: "",
      userList: [], // 曾经有过对话的会话列表




      netcall: null,
      callTimer: null,      // 呼叫超时计时器
      beCalledInfo: null,   // 被叫信息
      beCalling: false,     // 是否处于被叫中
    }
  },
  components: {},
  mounted() {
    document.title = this.myUser.account
    this.content()
  },
  methods: {
    initVideo() {
      console.log('初始化音视频')
      NIM.use(WebRTC)
      this.netcall = WebRTC.getInstance({
        nim: this.nim,
        container: document.getElementById('my_container'),
        remoteContainer: document.getElementById("you_container"),
        debug: true
      })
      this.callSomeone()

      this.onBeCall()
      this.onAcceptCall()

      this.netcall.getDevices().then(obj => {
        console.log('获取设备列表', obj)
      })
    },
    callSomeone() { // 呼叫
      this.netcall.call({
        type: WebRTC.NETCALL_TYPE_VIDEO,
        webrtcEnable: true,
        account: this.toUser.account,
        pushConfig: {
          enable: true,
          needBadge: true,
          needPushNick: true,
          pushContent: '',
          custom: '测试自定义数据',
          pushPayload: '',
          sound: '',
          forceKeepCalling: 0
        },
        sessionConfig: {
          videoQuality: WebRTC.CHAT_VIDEO_QUALITY_NORMAL,
          videoFrameRate: WebRTC.CHAT_VIDEO_FRAME_RATE_15,
          videoBitrate: 0,
          recordVideo: false,
          recordAudio: false,
          highAudio: false,
          bypassRtmp: false,
          rtmpUrl: '',
          rtmpRecord: false,
          splitMode: WebRTC.LAYOUT_SPLITLATTICETILE
        }
      }).then(() => {
        console.log(`成功发起了呼叫${this.myUser.account}呼叫了${this.toUser.account}`)
        this.showAcceptUI(null, '1212')
        this.onControl()
        // 超时之后挂断
        this.callTimer = setTimeout(() => { if (!this.netcall.callAccepted) this.onHangups() }, 1000 * 30)
      }).catch(err => {
        if (err.event.code == 11001) console.log('被叫不在线', err)
      })
    },
    onBeCall() { // 被叫收到呼叫通知
      let type = null,   // 呼叫类型
          busy = false   // 是否正忙
      
      this.netcall.on("beCalling", obj => {
        console.log(`收到了来自${this.myUser.account}的呼叫`)
        let channelId = obj.channelId
        // 被叫回应主叫自己已经收到了通话请求
        this.netcall.control({
          channelId: channelId,
          command: WebRTC.NETCALL_CONTROL_COMMAND_START_NOTIFY_RECEIVED
        })


        // 只有在没有通话并且没有被叫的时候才记录被叫信息, 否则通知对方忙并拒绝通话
        if (!this.netcall.calling && !this.beCalling) {
          type = obj.type
          this.beCalling = true
          this.beCalledInfo = obj

          this.showAcceptUI(obj, null)
        } else {
          if (this.netcall.calling) {
            busy = this.netcall.notCurrentChannelId(obj)
          } else if (this.beCalling) {
            busy = this.beCalledInfo.channelId !== channelId
          }
          console.log('是否忙线', busy)
          if (busy) {
            this.netcall.control({
              channelId: channelId,
              command: WebRTC.NETCALL_CONTROL_COMMAND_BUSY
            })
            // 拒绝通话
            this.netcall.response({
              accepted: false,
              beCalledInfo: obj
            })
          }
        }
      })
    },
    acceptCall() { // 接听音视频被呼叫
      this.beCalling = false
      console.log('接听呼叫----', this.beCalledInfo)
      this.netcall.response({
        accepted: true,
        beCalledInfo: this.beCalledInfo,
        sessionConfig: {
          videoQuality: WebRTC.CHAT_VIDEO_QUALITY_NORMAL,
          videoFrameRate: WebRTC.CHAT_VIDEO_FRAME_RATE_15,
          videoBitrate: 0,
          recordVideo: false,
          recordAudio: false,
          highAudio: false,
          bypassRtmp: false,
          rtmpUrl: '',
          rtmpRecord: false,
          splitMode: WebRTC.LAYOUT_SPLITLATTICETILE
        }
      }).catch(err => {
        this.netcall.control({
          channelId: this.beCalledInfo.channelId,
          command: WebRTC.NETCALL_CONTROL_COMMAND_BUSY
        })
        this.onHangups()
        this.beCalledInfo = null
        console.log('接听失败', err)
      })
    },
    onAcceptCall(obj) { // 被叫接受的通知
      this.netcall.on('callAccepted', obj => {
        console.log('被叫接受的通知', obj)
        this.clearCallTimer()
        
        let promise;
        if (obj.type === WebRTC.NETCALL_TYPE_VIDEO) {
          document.querySelector('.ui_container').style.display = 'none'
          this.startConnect()
        }
      })
    },
  startConnect() {
    let _a = WebRTC.DEVICE_TYPE_AUDIO_IN
    // this.netcall.getDevicesOfType(_a).then(obj => {
    //   alert(`检测设备类型, ${JSON.stringify(obj)}`)
    //   console.log('==================', obj)
    // })
    

    // 连接媒体网关
    this.netcall.startRtc()
      .then(() => { // 开启麦克风
        return this.netcall.startDevice({
            type: WebRTC.DEVICE_TYPE_AUDIO_IN
        }).catch(err => {
            console.log('启动麦克风失败00000');
            console.error(err)
            alert(`麦克风xxxxxx，${err}`)
        })
      })
      .then(() => {
        this.netcall.setCaptureVolume(255) // 设置采集音量
        return this.netcall.startDevice({ // 开启摄像头
          type: WebRTC.DEVICE_TYPE_VIDEO
        })
        .catch(err => {
          console.log('启动摄像头失败');
          console.error(err)
          alert(`启动摄像头失败，${err.desc}`)
        })
      })
      .then(() => {
        this.netcall.startLocalStream( //预览本地画面
          document.getElementById('my_container')
        )

        this.netcall.setVideoViewSize({ // 设置本地预览画面大小
          width: 300,
          height: 300,
          cut: true
        })

         // 预览对方视频画面
        this.netcall.startRemoteStream({
            account: this.toUser.account,
            node: document.getElementById('you_container')
        })
        // 设置对方预览画面大小
        this.netcall.setVideoViewRemoteSize({
            account: this.toUser.account,
            width: 300,
            height: 300,
            cut: true
        })

      })
      .catch(err => {
          console.log('发生错误', err)
          this.hangups()
      })

      this.netcall.startDevice({
          type: WebRTC.DEVICE_TYPE_AUDIO_OUT_CHAT
      }).catch(function (err) {
          console.log('播放对方的声音失败', err)
      })
       

    },
    rejectCall() { // 拒绝接听
      this.netcall.control({
        channelId: this.beCalledInfo.channelId,
        command: WebRTC.NETCALL_CONTROL_COMMAND_BUSY
      })
      this.netcall.response({
        accepted: false,
        beCalledInfo: this.beCalledInfo
      })
      this.beCalledInfo = null
      this.beCalling = false
    },
    onRejectCall(obj) { // 被叫拒绝的通知
      this.netcall.on('callRejected', obj => {
        console.log('被叫拒绝的通知', obj)
        // 如果呼叫之前，启动了超时倒计时，这里可以取消呼叫倒计时
        this.clearCallTimer()
        this.onHangups()
      })
    },
    onHangups() { // 监听挂断事件
      this.netcall.hangup()
      this.resetWhenHangup()
    },
    resetWhenHangup () { // 挂断之后 清理
      this.beCalledInfo = null
      this.beCalling = false
      this.clearCallTimer()
      this.netcall.hangup()
      // this.netcall.stopLocalStream()
      // this.netcall.stopRemoteStream()
      // this.netcall.stopDeviceAudioIn()
      // this.netcall.stopDeviceAudioOutLocal()
      // this.netcall.stopDeviceAudioOutChat()
      // this.netcall.stopDeviceVideo()
    },
    clearCallTimer() { // 清理 成功发起呼叫之后设置的定时器
      clearTimeout(this.callTimer)
    },
    showAcceptUI(obj, accid) { // 展示接听UI界面
      console.log('展示接听UI界面')
    },
    


    startDeviceVideo() { // 启动摄像头
      this.netcall.startDevice({
        type: WebRTC.DEVICE_TYPE_VIDEO,
        width: 300,
        height: 300
      }).then(() => {
        console.log('启动成功')
        // 通知对方自己开启了摄像头
        this.netcall.control({
          command: WebRTC.NETCALL_CONTROL_COMMAND_NOTIFY_VIDEO_ON
        })

        this.netcall.startLocalStream() // 开启本地视频流
        setTimeout(() => {
          this.startDeviceAudioIn()
        }, 1000)
        
        setTimeout(() => {
          this.netcall.startRtc()
        }, 2000)
        
        setTimeout(() => {
          this.startDeviceAudioOutChat()
        }, 3000)
      }).catch(() => {
        // 通知对方自己的摄像头不可用
        this.netcall.control({
          command: WebRTC.NETCALL_CONTROL_COMMAND_SELF_CAMERA_INVALID
        })
        console.log('启动摄像头失败1111')
      })
    },
    stopDeviceVideo () { // 停止摄像头
      this.netcall.stopDevice(WebRTC.DEVICE_TYPE_VIDEO).then(() => {
        // 通知对方自己关闭了摄像头
        this.netcall.control({
          command: WebRTC.NETCALL_CONTROL_COMMAND_NOTIFY_VIDEO_OFF
        })

        this.netcall.stopRemoteStream() // 停止远程视频流
        this.netcall.stopLocalStream()  // 停止本地视频流
      })
    },
    startDeviceAudioIn() { // 启动麦克风设备
      return this.netcall.startDevice({
        type: WebRTC.DEVICE_TYPE_AUDIO_IN,
        device
      }).then(() => {
        // 通知对方自己开启了麦克风
        this.netcall.control({
          command: WebRTC.NETCALL_CONTROL_COMMAND_NOTIFY_AUDIO_ON
        })
      }).catch(err => {
        console.log('启动麦克风失败')
        alert(`启动麦克风失败，${err.desc}`)
      })
    },
    startDeviceAudioOutLocal() { // 启动播放自己声音的设备
      return this.netcall.startDevice({
        type: WebRTC.DEVICE_TYPE_AUDIO_OUT_LOCAL,
        device
      }).catch(() => {
        console.log('播放自己的声音失败')
      })
    },
    stopDeviceAudioOutLocal() { // 停止播放自己声音的设备
       return this.netcall.stopDevice(WebRTC.DEVICE_TYPE_AUDIO_OUT_LOCAL)
    },
    startDeviceAudioOutChat() { // 启动播放对方声音的设备
      return this.netcall.startDevice({
        type: WebRTC.DEVICE_TYPE_AUDIO_OUT_CHAT,
        device
      }).catch(() => {
        console.log('播放对方的声音失败')
      })
    },
    stopDeviceAudioOutChat() { // 停止播放对方声音的设备
      return this.netcall.stopDevice(WebRTC.DEVICE_TYPE_AUDIO_OUT_CHAT)
    },
    onControl(obj) { // 监听音视频通话控制指令
      this.netcall.on('control', obj => {
        // 如果不是当前通话的指令, 直接丢掉
        if (this.netcall.notCurrentChannelId(obj)) {
          return
        }
        console.log('on control', obj)
        const {type} = obj
        switch (type) {
          // NETCALL_CONTROL_COMMAND_NOTIFY_AUDIO_ON 通知对方自己打开了音频
          case WebRTC.NETCALL_CONTROL_COMMAND_NOTIFY_AUDIO_ON:
            console.log('对方打开了音频')
            break
          // NETCALL_CONTROL_COMMAND_NOTIFY_AUDIO_OFF 通知对方自己关闭了音频
          case WebRTC.NETCALL_CONTROL_COMMAND_NOTIFY_AUDIO_OFF:
            console.log('对方关闭了音频')
            break
          // NETCALL_CONTROL_COMMAND_NOTIFY_VIDEO_ON 通知对方自己打开了视频
          case WebRTC.NETCALL_CONTROL_COMMAND_NOTIFY_VIDEO_ON:
            console.log('对方打开了视频')
            break
          // NETCALL_CONTROL_COMMAND_NOTIFY_VIDEO_OFF 通知对方自己关闭了视频
          case WebRTC.NETCALL_CONTROL_COMMAND_NOTIFY_VIDEO_OFF:
            console.log('对方关闭了视频')
            break
          // NETCALL_CONTROL_COMMAND_BUSY 占线
          case WebRTC.NETCALL_CONTROL_COMMAND_BUSY:
            console.log('对方忙')
            break
          // NETCALL_CONTROL_COMMAND_SELF_CAMERA_INVALID 自己的摄像头不可用
          // NETCALL_CONTROL_COMMAND_SELF_ON_BACKGROUND 自己处于后台
          // NETCALL_CONTROL_COMMAND_START_NOTIFY_RECEIVED 告诉发送方自己已经收到请求了（用于通知发送方开始播放提示音）
          // NETCALL_CONTROL_COMMAND_NOTIFY_RECORD_START 通知对方自己开始录制视频了
          // NETCALL_CONTROL_COMMAND_NOTIFY_RECORD_STOP 通知对方自己结束录制视频了
        }
      })

    },










    sendMsg() {
      var msg = this.nim.sendText({
        scene: "p2p",
        to: "aa",
        text: this.sendText,
        done(err, msg) {
          console.log(err, msg);
        }
      });
    },
    content() {
      // 建立im连接
      this.nim = NIM.getInstance({
        appKey: "2b70cec80ec40626d76df0539e87bfb1",
        account: this.myUser.account,
        token: this.myUser.token,
        customTag: "tag",
        onconnect: this.onConnect, // 连接建立成功
        onerror: this.onError, // 建立失败
        onwillreconnect: this.onWillReconnect, // 即将重连
        ondisconnect: this.onDisconnect, // 断开连接
        onloginportschange: this.onLoginPortsChange, // 多端登录状态变化
        onsessions: this.onSessions, // 同步最近会话列表
        onupdatesession: this.onUpdateSession, // 更新会话 -- 发送/接收/重置
        onsyncdone: this.onSyncDone, // 数据同步完成
        onsysmsg: this.onSysMsg,
        oncustomsysmsg: this.onCustomSysMsg
      });
    },
    onConnect(msg) {
      console.log("im连接建立成功", msg);
      this.initVideo();
    },
    onError(msg) {
      console.log("error", msg);
      window.location.reload();
    },
    onWillreconnect(msg) {
      console.log("onWillreconnect", msg);
    },
    onDisconnect(msg) {
      console.log("onDisconnect", msg);
      this.imLog ? "" : this.$alert("您的账号已在其他设备登录");
    },
    onLoginPortsChange(msg) {
      console.log("onLoginPortsChange", msg);
    },
    onSessions(msg) {
      console.log("onSessions", msg);
      this.userList = msg;
    },
    onUpdateSession(msg) {
      // 更新信息 -- 接收消息的时候触发
      console.log("onUpdateSession", msg);
      if (this.isFirst != 4) {
        if (msg && msg.lastMsg && msg.lastMsg.from != this.myUser.account) {
          // this.showMsgData.push(msg.lastMsg);
          // setTimeout(() => {
          //   this.setScrllTop();
          // }, 100);
        }
      }
    },
    onSyncDone(msg) {}
  }
};
</script>
<style lang="scss" scoped>
.ui_container{
  width: 100%;
  height: 100%;
  position: fixed;
}
.overBackground{
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  position: absolute;
  background-color: #4f4f4f;
}
.btn_img{
  left: 0;
  bottom: 0;
  width: 100%;
  display: flex;
  height: 200px;
  position: absolute;
  align-items: center;
  justify-content: space-between;
  img{
    max-height: 70px;
  }
}
.user_info{
  left: 0;
  top: 100px;
  width: 100%;
  height: 200px;
  display: flex;
  align-items: center;
  position: absolute;
  justify-content: center;
  div{
    
    span{
      text-align: center;
      display: block;
      &:first-child{
        width: 100px;
        height: 100px;
        background: url('../assets/12.jpeg') no-repeat center;
        background-size: cover;
      }
      &:last-child{
        color: #fff;
        line-height: 40px;
      }
    }
  }
}

.my_container{
  top: 0;
  left: 0;
  position: fixed;
}
.you_container{
  bottom: 0;
  left: 0;
  position: fixed;
}
</style>